/*
 * BPlusTree.h
 *
 *  Created on: 30 Sep, 2009
 *      Author: Pankaj Parakh
 */

#ifndef BPLUSTREE_H_
#define BPLUSTREE_H_

#include "../common.h"
#include "../BufferManager/BufferManager.h"
#include "../Page.h"
//#include "../yADBMS.h"

#include<vector>

#define EQUAL 0
#define INCLUDE 1
#define EXCLUDE 2

namespace BPlusTreeUI
{
	int indexui();
}


class BPlusTree {
#define BASIC_NODE_SIZE (sizeof(int)*2 + sizeof(dp))
#define BASIC_LNODE_SIZE (sizeof(dp)*2)
#define BASIC_INODE_SIZE (0)

public:
	typedef yadbms_common::rid rid;

	typedef struct diskptrstruct{
		long ptr;
	}dp;

	typedef struct inodestruct{
		unsigned char** key;
		dp* ptr;
	}inode;

	typedef struct lnodestruct{
		dp prev;
		dp next;
		unsigned char** key;
		rid* record;
	}lnode;

	typedef struct nodestruct{
		int level;
		int no_of_keys;
		dp parent;
		union {
			lnode ldata;
			inode idata;
		}data;
		//unsigned char* junkdata;
	}node;

	typedef struct searchresultstruct{
		unsigned char* key;
		rid record;
	}searchresult;


private:
	BufferManager *_buffer;// = database::buffer;
	vector<Page*> _pagelist;
	int _fanout;
	unsigned char* _keyformat;
	int	_keysize;
	int _node_size;
	int _nos_key_attr;
	int _nos_lnode_keys;
	dp _root;
	int _rootheadpage;

	BPlusTree();

	void init(int fanout,unsigned char* keyformat,int nos_key_attr);

	void copyKey(unsigned char* skey,unsigned char** dkey);

	dp createNewNode(int levelno);

	node* getNodePtr(dp node);

	node* getNodePtr(dp nod,int dirty);

	void setNodePtr(dp* rnodedp,node* rnode);

	int keyComp(unsigned char* key1,unsigned char* key2);

	dp splitNode(node* rnode,dp rnodedp,unsigned char* key,void* rid);

	dp insertLnode(node* rnode,dp rnodedp,unsigned char*key, rid record);

	dp insertInode(node* rnode,dp rnodedp,unsigned char*key,dp lchild,dp rchild);

	void printTreeRec(dp rnodedp);

	void printTreeNode(dp rnodedp);

	void updateChildInfo(node* rnode,dp rnodedp);

	dp searchNode(unsigned char * key);

	bool compareRid(rid rid1,rid rid2);

	bool compareDp(dp dp1,dp dp2);

	dp deleteLNode(node* expnode,dp expnodedp,unsigned char* key,rid record);

	void updateParents(node* rnode,dp rnodedp);

	dp deleteINode(node* expnode,dp expnodedp);

	void deletePage(dp pageno);

	dp getPrevINode(node* rnode,dp rnodedp);

	dp getNextINode(node* rnode,dp rnodede);

	void setRoot(dp root);

	void unPinPages();

	Page* getPage(long pageno);





public:

	BPlusTree(int fanout,unsigned char* keyformat,int nos_key_attr,int *rootheadpage);

	BPlusTree(int fanout,unsigned char* keyformat,int nos_key_attr,int rootheadpage);

	void insert(unsigned char* key,rid record);

	rid search(unsigned char* key);

	int search(unsigned char* key,std::vector<searchresult> *list);

	int rangeSearch(unsigned char* key1,unsigned char* key2,std::vector<searchresult> *vrid,int mode1,int mode2);

	bool deleteEntry(unsigned char* key,rid record);

	void printTree();

	void printNode(dp nodedp);

	void printKey(unsigned char* key);

	void printDetails();

	void bulkLoad(long first,long last,long step);

	dp getRoot();

	//BPlusTree();
	~BPlusTree();
};

#endif /* BPLUSTREE_H_ */
